package com.winit.openapi.apiadapter.controller.builder;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.winit.common.query.Page;
import com.winit.common.spi.SPIException;
import com.winit.common.spi.context.CommandContext;
import com.winit.oms.spi.outbound.OutboundOrderRevenueService;
import com.winit.oms.spi.outbound.OutboundOrderTrackingService;
import com.winit.oms.spi.outbound.command.order.QueryOrderBySellerCommand;
import com.winit.oms.spi.outbound.command.order.QueryOrderRevenueCommand;
import com.winit.oms.spi.outbound.command.order.QueryOrderTrackingCommand;
import com.winit.oms.spi.outbound.vo.OutboundOrderEnumContants.OrderSource;
import com.winit.oms.spi.outbound.vo.OutboundOrderEnumContants.OrderType;
import com.winit.oms.spi.outbound.vo.OutboundOrderVo;
import com.winit.oms.spi.outbound.vo.order.OutboundOrderMerchandiseVo;
import com.winit.oms.spi.outbound.vo.order.OutboundOrderRevenueVo;
import com.winit.oms.spi.outbound.vo.order.OutboundOrderTrackingVo;
import com.winit.oms.spi.outbound.vo.order.OutboundOrderValueAddedServiceVo;
import com.winit.oms.spi.outbound.vo.order.OutboundOrderVasAttributeVo;
import com.winit.oms.spi.vas.command.QueryVasOrderCommand;
import com.winit.oms.spi.vas.service.VasOrderServiceSnapshotService;
import com.winit.oms.spi.vas.vo.VasOrderServiceSnapshotVo;
import com.winit.oms.spi.vo.EbayOrderVo;
import com.winit.oms.spi.vo.v2.order.BuyerInfo;
import com.winit.oms.spi.vo.v2.order.CustomerInfo;
import com.winit.oms.spi.vo.v2.order.ProductInfo;
import com.winit.oms.spi.vo.v2.order.WarehouseInfo;
import com.winit.openapi.constants.ApiConstant;
import com.winit.openapi.constants.EnumConstant;
import com.winit.openapi.constants.EnumConstant.OrderStatus;
import com.winit.openapi.constants.EnumConstant.SLAStatus;
import com.winit.openapi.constants.ErrorCode;
import com.winit.openapi.exception.ApiException;
import com.winit.openapi.model.RequestMsg;
import com.winit.openapi.model.ResponseMsg;
import com.winit.openapi.util.DateUtil;
import com.winit.openapi.wh.outbound.validator.OutboundOrderfieldValidator;
import com.winit.pms.spi.v2.common.PmsEnumType.BillingUnit;
import com.winit.pms.spi.v2.instance.pscInstance.ProductInstanceService;
import com.winit.pms.spi.v2.instance.pscInstance.command.ProductInstanceByDeliveryModeCommand;
import com.winit.pms.spi.v2.instance.pscInstance.command.ProductInstanceCommand;
import com.winit.pms.spi.v2.instance.pscInstance.vo.ProductInstance;
import com.winit.ups.spi.command.CodeCommand;
import com.winit.ups.spi.warehouse.WarehouseService;
import com.winit.ups.spi.warehouse.command.QueryWarhouseByIdCommand;
import com.winit.ups.spi.warehouse.vo.WarehouseVo;

@Service("orderAdapteBuilder")
public class OrderAdapteBuilder {

    private static final Logger                 logger                     = LoggerFactory.getLogger(OrderAdapteBuilder.class);

    /**
     * 出库单费用项code：订单处理费
     */
    private static final String                 ORDER_HANDLING_CHARGE_CODE = "1000914";
    /**
     * 出库单费用项code：派送费
     */
    private static final String                 ORDER_DELIVERY_CHARGE_CODE = "1000010";
    /**
     * 出库单费用项code：winit返利
     */
    private static final String                 ORDER_RETURN_CHARGE_CODE   = "1000855";
    /**
     * 费用推送状态：
     */
    private static final String                 ORDER_FEE_PUSH_SUCCESS     = "Success";

    @Resource
    private WarehouseService                    upsWarehouseService;

    @Resource
    private ProductInstanceService              productInstanceService;

    @Resource
    private OutboundOrderRevenueService         outboundOrderRevenueService;

    @Resource
    private OutboundOrderTrackingService        outboundOrderTrackingService;

    @Resource
    private VasOrderServiceSnapshotService      vasOrderServiceSnapshotService;

    /**
     * 缓存仓库
     */
    private static Map<Long, WarehouseVo>       warehouseMap               = new HashMap<Long, WarehouseVo>();

    private static Map<String, ProductInstance> winitProdectMap            = new HashMap<String, ProductInstance>();

    public QueryOrderBySellerCommand buildQueryOutboundCommand(JSONObject json) {
        QueryOrderBySellerCommand command = new QueryOrderBySellerCommand();
        OutboundOrderVo vo = new OutboundOrderVo();
        if (json.containsKey("outboundOrderNum")) {// 订单号
            vo.setOrderNo(json.getString("outboundOrderNum"));
        }
        if (json.containsKey("sellerOrderNo")) {// 卖家订单号
            vo.setSellerOrderNo(json.getString("sellerOrderNo"));
        }
        if (json.containsKey("status")) {// 订单状态
            vo.setStatus(json.getString("status"));
        }
        // 收件人信息
        if (json.containsKey("receiverName")) {// 收件人姓名
            BuyerInfo buyerInfo = new BuyerInfo();
            buyerInfo.setBuyerName(json.getString("receiverName"));
            vo.setBuyerInfoVo(buyerInfo);
        }
        if (json.containsKey("warehouseId")) {// 发货仓编号
            WarehouseVo warehouseVo = getWarehouseById(json.getLong("warehouseId"));
            if (null != warehouseVo) {
                WarehouseInfo warehouseInfo = new WarehouseInfo();
                warehouseInfo.setWarehouseCode(warehouseVo.getCode());
                vo.setDispatchWarehouseInfo(warehouseInfo);
            }
        }
        if (json.containsKey("trackingNo")) {// 快递单号
            List<String> tList = new ArrayList<String>();
            tList.add(json.getString("trackingNo"));
            vo.setTrackingNo(tList);
        }
        List<OutboundOrderMerchandiseVo> mList = new ArrayList<OutboundOrderMerchandiseVo>();
        OutboundOrderMerchandiseVo mvo = new OutboundOrderMerchandiseVo();
        if (json.containsKey("productValue")) {// 商品编码
            mvo.setMerchandiseCode(json.getString("productValue"));
        }
        if (json.containsKey("productName")) {// 商品名称
            mvo.setNameCn(json.getString("productName"));
        }
        mList.add(mvo);
        vo.setMerchandiseInfoList(mList);
        if (json.containsKey("bookingOperator")) {// 客户名称（下单人）
            CustomerInfo customerInfo = new CustomerInfo();
            customerInfo.setCustomerName(json.getString("bookingOperator"));
            vo.setCustomerInfo(customerInfo);
        }
        // 转为时间类型.
        if (json.containsKey("dateOrderedStartDate")) {// 开始时间
            String orderDateStart = json.getString("dateOrderedStartDate");
            orderDateStart += " 00:00:00";
            Date from = DateUtil.parse2Date(orderDateStart, DateUtil.FULL_DATE_STRING);
            vo.setOrderStartDate(from);
        }
        if (json.containsKey("dateOrderedEndDate")) {// 结束时间
            String orderDateEnd = json.getString("dateOrderedEndDate");
            orderDateEnd += " 23:59:59";
            Date end = DateUtil.parse2Date(orderDateEnd, DateUtil.FULL_DATE_STRING);
            vo.setOrderEndDate(end);
        }
        command.setOutboundOrderVo(vo);

        return command;
    }

    public Map<String, Object> buildOutboundOrderListAdaptePageVo(OutboundOrderVo vo) {
        Map<String, Object> map = new HashMap<String, Object>();

        map.put("exwarehouseId", vo.getOrderId());
        map.put("documentNo", vo.getOrderNo());// 订单编号.
        map.put("sellerOrderNo", vo.getSellerOrderNo());// 卖家订单号
        map.put("status", vo.getStatus());// 订单状态
        // 添加作废失败原因
        buildVoidOrderTrack(vo, map);
        map.put("statusName", getStatusName(vo.getStatus()));
        map.put("ontimeStatus", vo.getOntimeTrack());// 准时派送状态：准时：PT 迟到：BL
                                                     // 进行中：IP
        map.put("storageOntime", getOnTimeName(vo.getOntimeTrack()));// 准时派送状态名称
        map.put("serviceStandardTime", vo.getServiceNormDay());
        map.put("serviceCompleteTime", vo.getServiceCompletionDay());

        // 收件人信息
        BuyerInfo buyerInfo = vo.getOriginalBuyerInfo();
        if (buyerInfo != null) {
            map.put("name", buyerInfo.getBuyerName());
            map.put("postal", buyerInfo.getBuyerPostcode());
        }

        EbayOrderVo ebayOrderVo = vo.getEbayOrderVo();
        if (ebayOrderVo != null) {
            map.put("eBaySellerID", ebayOrderVo.getEbaySellerId());// eBaySellerID
            map.put("sellerOrderNo", ebayOrderVo.getEbayOrderNo());// eBaySellerNo
            map.put("is_ebay_plus", ebayOrderVo.getIsEbayPlus());// eBay+

        }
        map.put("sellerOrderNo", vo.getSellerOrderNo());// eBaySellerNo
        map.put("isEBayOrder", ebayOrderVo == null ? "N" : "Y");
        // 仓库信息
        WarehouseInfo warehouseInfo = vo.getDispatchWarehouseInfo();
        if (warehouseInfo != null) {
            // 仓库名称.
            map.put("warehouseName", warehouseInfo.getWarehouseName());// 仓库名称
            map.put("countryName", warehouseInfo.getCountryName());// 国家名称
            map.put("warehouseCode", warehouseInfo.getWarehouseCode());// 国家名称
            WarehouseVo warehouseVo = getWarehouseByCode(warehouseInfo.getWarehouseCode());
            if (null != warehouseVo) {
                map.put("warehouseId", warehouseVo.getWarehouseId());
            }

        }
        // 客户信息
        CustomerInfo customerInfo = vo.getCustomerInfo();
        if (customerInfo != null) {
            String customerCode = customerInfo.getCustomerCode();
            try {
                Long customerId = Long.valueOf(customerCode);
                map.put("cBpartnerId", customerId);
            } catch (Exception e) {
                map.put("cBpartnerId", customerCode);
            }
            map.put("cBpartnerId", Long.valueOf(customerInfo.getCustomerCode()));
            map.put("bpName", customerInfo.getCustomerName());
        }

        // 产品信息
        ProductInfo productInfo = vo.getProductInfo();
        if (productInfo != null) {
            map.put("deliverywayName", productInfo.getWinitProductName());
            map.put("winitProductCode", productInfo.getWinitProductCode());
            ProductInstance product = getProductByCode(productInfo.getWinitProductCode());
            Long deliveryId = null;
            if (null != product) {
                try {
                    deliveryId = Long.valueOf(product.getDeliveryMode());
                    map.put("deliverywayId", deliveryId);
                } catch (NumberFormatException e) {
                    map.put("deliverywayId", deliveryId);
                    logger.warn("无效的派送方式ID： " + deliveryId);
                }
            }
        }

        map.put("dateOrdered", vo.getOrderTime());// 下单时间
        map.put("dateFinish", vo.getOutWhTime());// 出库时间
        map.put("finishedTime", vo.getFinishedTime());// 完成时间
        map.put("ontimeTrack", vo.getOntimeTrack());// 准时派送.
        map.put("serviceNormDay", vo.getServiceNormDay());// 服务标准天数
        map.put("serviceCompletionDay", vo.getServiceCompletionDay());// 服务完成天数

        map.put("cFromBpartnerId", vo.getFromCBPartnerId());
        map.put("cToBpartnerId", vo.getToCBPartnerId());
        map.put("isShareOrder", vo.isShareOrder() ? "Y" : "N");
        map.put("isRepeat", vo.getIsRepeat());
        map.put("isAddressError", "");
        map.put("errorMsg", "");
        map.put("winit_trackingno", vo.getWinitTrackingNo());// Winit 跟踪号

        map.put("weight", vo.getWeight());
        map.put("sellerWeight", null);
        map.put("volume", vo.getVolume());

        // 预估费用字段
        map.put("estimateFees", vo.getEstimateAmount());
        map.put("currency", vo.getCurrencyCode());

        // 商品信息
        List<OutboundOrderMerchandiseVo> merchandiseInfoList = vo.getMerchandiseInfoList();
        // 老的出库接口sku字段格式：商品编码+"@@"+商品数量+"@@"+商品M码+"@@",多少商品直接用","隔开
        // eg:D00101(return)@@1@@RMUS00000000002450@@,2U-E92-RA-TCSL(return)@@1@@RMUS00000000002448@@
        StringBuffer skuStr = new StringBuffer();
        if (null != merchandiseInfoList && merchandiseInfoList.size() > 0) {
            for (OutboundOrderMerchandiseVo tempVo : merchandiseInfoList) {
                skuStr.append(tempVo.getMerchandiseCode());
                skuStr.append("@@");
                skuStr.append(tempVo.getEstimateDispatchQty());// 预计出库数量
                skuStr.append("@@");
                skuStr.append(tempVo.getMerchandiseSerno());
                skuStr.append("@@");
                skuStr.append(",");
            }
        }
        if (skuStr.toString().contains(",")) {
            skuStr.deleteCharAt(skuStr.lastIndexOf(","));
        }
        map.put("sku", skuStr.toString());
        map.put("itemqty", vo.getAutalItemQty());
        // trackingNo
        StringBuffer trackNoStr = new StringBuffer();
        // 现在trackingNo是列表
        List<String> list = vo.getTrackingNo();
        if (null != list) {
            for (String trackingNo : list) {
                trackNoStr.append(trackingNo).append(",");
            }
        }
        if (trackNoStr.toString().contains(",")) {
            trackNoStr.deleteCharAt(trackNoStr.lastIndexOf(","));
        }
        map.put("trackingNo", trackNoStr.toString());
        map.put("winitTrackingNo", vo.getWinitTrackingNo());
        return map;
    }

    public List<Map<String, Object>> buildOrderDetailResult(OutboundOrderVo vo) {

        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();

        List<OutboundOrderMerchandiseVo> merchandiseList = vo.getMerchandiseInfoList();
        if (CollectionUtils.isEmpty(merchandiseList)) {
            list.add(buildOutboundOrderDetail(vo));
        } else {
            for (OutboundOrderMerchandiseVo merchandiseVo : merchandiseList) {
                Map<String, Object> orderDetail = buildOutboundOrderDetail(vo);
                orderDetail.put("productCode", merchandiseVo.getMerchandiseCode());
                orderDetail.put("productNum",
                    merchandiseVo.getActualDispatchQty() == null ? merchandiseVo.getEstimateDispatchQty() : merchandiseVo.getActualDispatchQty());
                orderDetail.put("specification", merchandiseVo.getSpecification());
                orderDetail.put("eBayItemID", merchandiseVo.getEbayItemId());
                orderDetail.put("eBayNo", merchandiseVo.getEbayTransactionId());
                list.add(orderDetail);

            }
        }

        return list;
    }

    private Map<String, Object> buildOutboundOrderDetail(OutboundOrderVo vo) {

        Map<String, Object> map = new HashMap<String, Object>();

        map.put("outboundOrderID", vo.getOrderId());
        map.put("outboundOrderNum", vo.getOrderNo());
        map.put("status", vo.getStatus());// 订单状态
        map.put("eBayValidateResult", vo.getEbayOrderVo().getEbayValidateResult());
        // 添加作废失败原因
        buildVoidOrderTrack(vo, map);
        map.put("statusName", getStatusName(vo.getStatus()));
        map.put("ontimeStatus", vo.getOntimeTrack());// 准时派送状态：准时：PT 迟到：BL
                                                     // 进行中：IP
        map.put("storageOntime", getOnTimeName(vo.getOntimeTrack()));// 准时派送状态名称
        map.put("serviceStandardTime", vo.getServiceNormDay());
        map.put("serviceCompleteTime", vo.getServiceCompletionDay());
        map.put("sellerOrderNo", vo.getSellerOrderNo() == null ? vo.getRepeatKey() : vo.getSellerOrderNo());// sellerOrderNo
        
        // 平台名称
        map.put("storeType", vo.getStoreType());

        // 收件人信息
        BuyerInfo buyerInfo = vo.getOriginalBuyerInfo();
        if (buyerInfo != null) {
            // 国家
            map.put("state", buyerInfo.getBuyerCountry());
            // 城市
            map.put("city", buyerInfo.getBuyerCity());
            // 收件人州
            map.put("regionName", buyerInfo.getBuyerState());
            // 收件人街道1
            map.put("address1", buyerInfo.getBuyerAddress1());
            // 收件人街道2
            map.put("address2", buyerInfo.getBuyerAddress2());
            // 收件人电话
            map.put("phoneNum", buyerInfo.getBuyerPhone());
            // 收件人姓名
            map.put("recipientName", buyerInfo.getBuyerName());
            // 收件人邮箱
            map.put("emailAddress", buyerInfo.getBuyerEmail());
            // 邮政编码
            map.put("zipCode", buyerInfo.getBuyerPostcode());
            // 门牌号
            map.put("doorplateNumbers", buyerInfo.getBuyerHouseNo());
        }

        EbayOrderVo ebayOrderVo = vo.getEbayOrderVo();
        if (ebayOrderVo != null) {
            map.put("eBaySellerID", ebayOrderVo.getEbaySellerId());// eBaySellerID
            map.put("eBayBuyerID", ebayOrderVo.getEbayBuyerId());
            map.put("eBayOrderID", ebayOrderVo.getEbayOrderId());
            // 交易日期
            map.put("transactionDate", ebayOrderVo.getEbayPayTime());

        }
        map.put("isEBayOrder", ebayOrderVo == null ? "N" : "Y");

        // 仓库信息
        WarehouseInfo warehouseInfo = vo.getDispatchWarehouseInfo();
        if (warehouseInfo != null) {
            // 仓库名称.
            map.put("warehouseName", warehouseInfo.getWarehouseName());// 仓库名称
            map.put("countryName", warehouseInfo.getCountryName());// 国家名称
            map.put("warehouseCode", warehouseInfo.getWarehouseCode());// 国家名称
            WarehouseVo warehouseVo = getWarehouseByCode(warehouseInfo.getWarehouseCode());
            if (null != warehouseVo) {
                map.put("warehouseId", warehouseVo.getWarehouseId());
            }

        }

        map.put("orderedTime", vo.getOrderTime());// 下单时间
        map.put("outboundDate", vo.getOutWhTime());// 出库时间
        map.put("status", vo.getStatus());// 订单状态
        map.put("statusName", getStatusName(vo.getStatus()));

        // 产品信息
        ProductInfo productInfo = vo.getProductInfo();
        if (productInfo != null) {
            map.put("deliverywayName", productInfo.getWinitProductName());
            map.put("winitProductCode", productInfo.getWinitProductCode());
            ProductInstance product = getProductByCode(productInfo.getWinitProductCode());
            Long deliveryId = null;
            if (null != product) {
                try {
                    deliveryId = Long.valueOf(product.getDeliveryMode());
                    map.put("deliverywayId", deliveryId);
                } catch (NumberFormatException e) {
                    map.put("deliverywayId", deliveryId);
                    logger.warn("无效的派送方式ID： " + deliveryId);
                }
            }
        }
        map.put("insuranceType", "No Insurance");
        // 最后一公里派送方式所用保险类型ID
        map.put("insuranceTypeID", 1000000);

        map.put("winitTrackingNo", vo.getWinitTrackingNo());// Winit 跟踪号
        StringBuffer trackNoStr = new StringBuffer();
        // 现在trackingNo是列表
        List<String> list = vo.getTrackingNo();
        if (null != list) {
            for (String trackingNo : list) {
                trackNoStr.append(trackingNo).append(",");
            }
        }
        if (trackNoStr.toString().contains(",")) {
            trackNoStr.deleteCharAt(trackNoStr.lastIndexOf(","));
        }
        map.put("trackingNum", trackNoStr.toString());

        // 派送公司名称
        map.put("carrier", vo.getCarrierName());
        // Ebay上显示的快递公司名
        map.put("ebayName", vo.getEbayName());
        // 包裹计费重量，kg
        map.put("chargeableWeight", vo.getWeight());

        buildOrderFee(map, vo);
        // 标准完成时间
        map.put("actualFinishTime", vo.getServiceNormDay());
        // 实际完成时间
        map.put("scheduledFinishTime", vo.getServiceCompletionDay());
        // 派送完成情况，及时与否
        map.put("deliveryCompletionStatus", vo.getOntimeTrack());
        // 客户信息
        CustomerInfo customerInfo = vo.getCustomerInfo();
        if (customerInfo != null) {
            String customerCode = customerInfo.getCustomerCode();
            try {
                Long customerId = Long.valueOf(customerCode);
                map.put("cBpartnerId", customerId);
            } catch (Exception e) {
                map.put("cBpartnerId", customerCode);
            }
            map.put("cBpartnerId", Long.valueOf(customerInfo.getCustomerCode()));
            map.put("bpName", customerInfo.getCustomerName());
        }

        map.put("cFromBpartnerId", vo.getFromCBPartnerId());
        map.put("cToBpartnerId", vo.getToCBPartnerId());
        map.put("isShareOrder", vo.isShareOrder() ? "Y" : "N");
        map.put("isRepeat", vo.getIsRepeat());

        return map;

    }

    private void buildOrderFee(Map<String, Object> map, OutboundOrderVo vo) {

        // 查询增值服务信息
        QueryVasOrderCommand queryVasCommand = new QueryVasOrderCommand();
        queryVasCommand.setCtx(CommandContext.getContext());
        queryVasCommand.setWinitOrderNo(vo.getOrderNo());
        List<VasOrderServiceSnapshotVo> vasList = vasOrderServiceSnapshotService.queryByWinitOrderNo(queryVasCommand);
        if (vasList != null && vasList.size() > 0) {
            map.put("VASFeeCost", 0);
        }
        map.put("deliveryCosts", 0);
        map.put("deliveryCostsCode", null);
        map.put("handlingfeeCode", null);
        map.put("handlingFee", 0);
        map.put("totalCost", 0);

        String orderNo = vo.getOrderNo();
        QueryOrderRevenueCommand command = new QueryOrderRevenueCommand();
        command.setOrderNo(orderNo);
        Page<OutboundOrderRevenueVo> feePage = outboundOrderRevenueService.getOrderRevenueByOrderNo(command);
        if (null == feePage || CollectionUtils.isEmpty(feePage.content)) {
            return;
        }
        // 总费用，总费用（所有费用之和），单位为USD
        BigDecimal totalFee = BigDecimal.ZERO;
        BigDecimal orderHandingFee = BigDecimal.ZERO;
        BigDecimal orderVasFee = BigDecimal.ZERO;
        for (OutboundOrderRevenueVo feeVo : feePage.content) {
            // 费用计算推送成功的才有效
            if (ORDER_FEE_PUSH_SUCCESS.equalsIgnoreCase(feeVo.getStatus())) {
                if ("VAS".equalsIgnoreCase(feeVo.getDocumentType())) {
                    // 增值服务费用
                    orderVasFee = orderVasFee.add(feeVo.getCurrencyAmount());
                    map.put("VASfeeCode", feeVo.getCurrencyCode());
                } else {
                    if (ORDER_DELIVERY_CHARGE_CODE.equals(feeVo.getChargeCode())) {
                        map.put("deliveryCosts", feeVo.getCurrencyAmount());
                        map.put("deliveryCostsCode", feeVo.getCurrencyCode());
                        // 由于各个费用项的收费节点不同，此处汇率给费用项最大的派送费用的汇率，仅供参考
                        map.put("rate", feeVo.getExRate());

                    } else if (ORDER_HANDLING_CHARGE_CODE.equals(feeVo.getChargeCode())) {
                        map.put("handlingfeeCode", feeVo.getCurrencyCode());
                        orderHandingFee = orderHandingFee.add(feeVo.getCurrencyAmount());

                    }

                }
                // 此处过滤掉WINIT返利费用,将其他费用加总作为订单总费用
                if (!ORDER_RETURN_CHARGE_CODE.equals(feeVo.getChargeCode())) {
                    totalFee = totalFee.add(feeVo.getAmount());
                } else {
                    // 添加返利费用项
                    map.put("rebateFeeCostsCode", feeVo.getCurrencyCode());
                    map.put("rebateFeeCosts", feeVo.getCurrencyAmount());
                }
            }
        }
        map.put("handlingFee", orderHandingFee);
        if (map.containsKey("VASFeeCost") || map.containsKey("VASfeeCode")) {
            map.put("VASFeeCost", orderVasFee);
        }
        map.put("totalCost", totalFee);

    }

    private static String getOnTimeName(String slaStatus) {
        if (StringUtils.isEmpty(slaStatus)) {
            return null;
        }
        SLAStatus[] statusEnum = EnumConstant.SLAStatus.values();
        for (SLAStatus status : statusEnum) {
            if (status.getStatus().equalsIgnoreCase(slaStatus)) {
                return status.getStatusName();
            }
        }
        return slaStatus;
    }

    private static String getStatusName(String status) {
        if (StringUtils.isEmpty(status)) {
            return null;
        }
        OrderStatus[] statusEnum = EnumConstant.OrderStatus.values();
        for (OrderStatus orderStatus : statusEnum) {
            if (orderStatus.getStatus().equalsIgnoreCase(status)) {
                return orderStatus.getStatusName();
            }
        }
        return status;
    }

    public static String convertChargeUnit(String chagerCode) {
        if (StringUtils.isEmpty(chagerCode)) {
            return null;
        }
        BillingUnit[] values = BillingUnit.values();
        for (BillingUnit billingUnit : values) {
            if (billingUnit.getType().equalsIgnoreCase(chagerCode)) {

                return billingUnit.getDescription();
            }
        }

        return chagerCode;
    }

    public WarehouseVo getWarehouseById(Long warehouseId) {
        if (null == warehouseId) {
            return null;
        }
        WarehouseVo warehouseVo = warehouseMap.get(warehouseId);
        if (null != warehouseVo) {
            return warehouseVo;
        } else {
            QueryWarhouseByIdCommand command = new QueryWarhouseByIdCommand();
            command.setWarehouseId(warehouseId);
            warehouseVo = upsWarehouseService.queryWarehouseById(command);
            if (null != warehouseVo) {
                warehouseMap.put(warehouseId, warehouseVo);
                return warehouseVo;
            }
        }
        return null;
    }

    public static Map<Long, WarehouseVo> getWarehouseMap() {
        return warehouseMap;
    }

    public static Map<String, ProductInstance> getWinitProdectMap() {
        return winitProdectMap;
    }

    public ProductInstance getProductByCode(String winitProductCode) {

        if (null == winitProductCode) {
            return null;
        }
        ProductInstanceCommand queryProductCommand = new ProductInstanceCommand();
        ProductInstance product = new ProductInstance();
        product.setCode(winitProductCode);
        queryProductCommand.setProduct(product);
        ProductInstance winitProduct = null;
        try {
            winitProduct = productInstanceService.getProductByCode(queryProductCommand);
        } catch (Exception e) {
            logger.warn("查询winit产品失败，无效的产品编码：" + winitProductCode);
        }
        if (null != winitProduct) {
            winitProdectMap.put(winitProductCode, winitProduct);

            return winitProduct;

        }
        return null;
    }

    public WarehouseVo getWarehouseByCode(String warehouseCode) {

        if (null == warehouseCode) {
            return null;
        }
        for (WarehouseVo vo : warehouseMap.values()) {
            if (vo.getCode().equalsIgnoreCase(warehouseCode)) {
                return vo;
            }
        }

        CodeCommand command = new CodeCommand();
        command.setCode(warehouseCode);
        WarehouseVo warehouseVo = upsWarehouseService.queryWarehouseByCode(command);
        if (null != warehouseVo) {
            warehouseMap.put(warehouseVo.getWarehouseId(), warehouseVo);
            return warehouseVo;
        }

        return null;
    }

    public JSONObject buildPagePara(RequestMsg requestMsg, ResponseMsg responseMsg) {
        JSONObject json = JSONObject.parseObject(requestMsg.getData().toString());
        int pageNo = json.getIntValue("pageNum") == 0 ? ApiConstant.PAGE_NO_DEFAULT : json.getIntValue("pageNum");
        int pageSize = json.getIntValue("pageSize") == 0 ? ApiConstant.PAGE_SIZE_DEFAULT : json.getIntValue("pageSize");
        JSONObject result = null;

        if (null != responseMsg.getData() && responseMsg.getData() instanceof JSONObject) {
            result = (JSONObject) responseMsg.getData();

        } else {
            result = new JSONObject();
            result.put("list", new ArrayList<Object>());
            result.put("total", 0);
        }
        result.put("currentPageNum", pageNo);
        result.put("currentPageSize", pageSize);
        return result;

    }

    /**
     * 该方法适用于老的AD下出库单的入参到OutboundOrderVo转换，包含草稿单和确认单，分销单
     * 
     * @param requestMsg
     * @return
     */
    public OutboundOrderVo buildOutboundOrderFromOldAPI(RequestMsg requestMsg) {
        JSONObject json = JSONObject.parseObject(requestMsg.getData().toString());
        OutboundOrderVo vo = new OutboundOrderVo();
        // 订单基本信息
        vo.setOrderType(StringUtils.isBlank(requestMsg.getPlatform()) ? ApiConstant.API_PLATFORM_SELLERERP : requestMsg.getPlatform());// 下单方式
        // 客户信息 这里只关注分销客户，普通客户由下游去上下文里面取
        if (StringUtils.isNotBlank(requestMsg.getAuz_app_key())) {// 分销商编码
            CustomerInfo customerInfo = new CustomerInfo();
            customerInfo.setDistributorCode((String) CommandContext.getContext().get(ApiConstant.API_DIS_BPARTNER_CODE));
            vo.setCustomerInfo(customerInfo);
            vo.setOrderSource(OrderSource.DP.getSource());
        }
        // 订单来源
        if ("GFS".equals(requestMsg.getPlatform())) {
            vo.setOrderSource(OrderSource.PS.getSource());
        }
        if (StringUtils.isEmpty(vo.getOrderSource())) {
            vo.setOrderSource(OrderSource.API.getSource());
        }
        
        // 添加平台名称字段
        if (json.containsKey("storeType")) {
            vo.setStoreType(json.getString("storeType"));
        }

        // 产品信息
        Long deliveryId = json.getLong("deliveryWayID");
        ProductInstanceByDeliveryModeCommand deliveryCommand = new ProductInstanceByDeliveryModeCommand();
        deliveryCommand.setDeliveryMode(String.valueOf(deliveryId));
        ProductInstance instance = null;
        try {
            instance = productInstanceService.getProductByDeliveryMode(deliveryCommand);
        } catch (SPIException e) {
            logger.error("根据deliveryMode:[" + deliveryCommand.getDeliveryMode() + "]查询winit产品失败,原因:" + e.getErrorMsg());
            throw new ApiException(ErrorCode.API_DELIVERY_NOT_EXISTS_ERROR, deliveryCommand.getDeliveryMode());
        }
        if (instance == null) {
            logger.error("根据派送方式ID:[" + deliveryCommand.getDeliveryMode() + "]查询winit产品失败。");
            throw new ApiException(ErrorCode.API_DELIVERY_NOT_EXISTS_ERROR, deliveryCommand.getDeliveryMode());
        }
        ProductInfo productInfo = new ProductInfo();
        productInfo.setWinitProductCode(instance.getCode());
        String orderType = OutboundOrderfieldValidator.getOrderType(instance.getCode());
        productInfo.setWinitProductName(instance.getName());
        productInfo.setWinitProductCategory3(orderType);
        productInfo.setDeliveryCode(String.valueOf(deliveryId));
        productInfo.setWinitProductName(instance.getName());
        vo.setProductInfo(productInfo);

        // 仓库信息构建
        Long warehouseId = json.getLong("warehouseID");
        QueryWarhouseByIdCommand command = new QueryWarhouseByIdCommand();
        command.setWarehouseId(warehouseId);
        WarehouseVo warehouseVo = upsWarehouseService.queryWarehouseById(command);
        if (warehouseVo == null) {
            logger.error("buildOutboundOrderFromOldAPI error,仓库ID:" + String.valueOf(warehouseId) + "对应的仓库不存在");
            throw new ApiException(ErrorCode.API_ADAPTE_WAREHOUSE_NOT_EXISTS, String.valueOf(warehouseId));
        }
        vo.setDispatchWarehouseInfo(buildWarehouseInfo(warehouseVo));

        // 买家信息构建
        BuyerInfo info = new BuyerInfo();
        // 收件人邮编
        info.setBuyerPostcode(StringUtils.stripToEmpty(json.getString("zipCode")));
        // 收件人国家
        info.setBuyerCountry(StringUtils.stripToEmpty(json.getString("state")));
        // 城市
        info.setBuyerCity(StringUtils.stripToEmpty(json.getString("city")));
        // 州、省
        info.setBuyerState(StringUtils.stripToEmpty(json.getString("region")));
        // 收货人姓名
        info.setBuyerName(StringUtils.stripToEmpty(json.getString("recipientName")));
        // 收货人电话
        info.setBuyerPhone(StringUtils.stripToEmpty(json.getString("phoneNum")));

        if (json.containsKey("address1")) {
            String buyerAddress1 = json.getString("address1");
            if (StringUtils.isNotBlank(buyerAddress1)) {
                buyerAddress1 = buyerAddress1.replace("\n", " ");
                info.setBuyerAddress1(buyerAddress1);
            }
        }
        if (json.containsKey("address2")) {
            String buyerAddress2 = json.getString("address2");
            if (StringUtils.isNotBlank(buyerAddress2)) {
                buyerAddress2 = buyerAddress2.replace("\n", " ");
                info.setBuyerAddress2(buyerAddress2);
            }
        }

        info.setBuyerEmail(StringUtils.stripToEmpty(json.getString("emailAddress")));
        info.setBuyerHouseNo(StringUtils.stripToEmpty(json.getString("doorplateNumbers")));
        vo.setBuyerInfoVo(info);
        if (OrderType.SP.getType().equals(orderType)) {
            // 取件人信息 原数据
            BuyerInfo originalBuyerInfo = new BuyerInfo();
            originalBuyerInfo.setBuyerName(StringUtils.stripToEmpty(json.getString("recipientName")));
            originalBuyerInfo.setBuyerPhone(StringUtils.stripToEmpty(json.getString("phoneNum")));
            vo.setOriginalBuyerInfo(originalBuyerInfo);
        }

        // eBay信息
        EbayOrderVo ebayOrderVo = new EbayOrderVo();
        // 商品信息
        List<OutboundOrderMerchandiseVo> merchandiseInfoList = new ArrayList<OutboundOrderMerchandiseVo>();
        JSONArray array = json.getJSONArray("productList");
        String isEbay = "N";
        for (Object item : array) {
            JSONObject merchandiseJson = (JSONObject) item;
            OutboundOrderMerchandiseVo merchandiseVo = new OutboundOrderMerchandiseVo();
            merchandiseVo.setMerchandiseCode(StringUtils.stripToEmpty(merchandiseJson.getString("productCode")));
            merchandiseVo.setSpecification(StringUtils.stripToEmpty(merchandiseJson.getString("specification")));
            merchandiseVo.setEstimateDispatchQty(merchandiseJson.getInteger("productNum"));
            merchandiseVo.setEbayItemId(StringUtils.trim(merchandiseJson.getString("eBayItemID")));
            merchandiseVo.setEbayTransactionId(StringUtils.trim(merchandiseJson.getString("eBayTransactionID")));
            // 这里会重复覆盖eBaySellerId和eBayBuyerId
            ebayOrderVo.setEbaySellerId(StringUtils.trim(merchandiseJson.getString("eBaySellerID")));
            ebayOrderVo.setEbayBuyerId(StringUtils.trim(merchandiseJson.getString("eBayBuyerID")));
            if (StringUtils.isNotEmpty(merchandiseJson.getString("eBayTransactionID"))
                || StringUtils.isNotEmpty(merchandiseJson.getString("eBayItemID"))) {
                isEbay = "Y";
            }
            merchandiseInfoList.add(merchandiseVo);
        }
        ebayOrderVo.setIsEbay(isEbay);
        vo.setEbayOrderVo(ebayOrderVo);
        vo.setMerchandiseInfoList(merchandiseInfoList);
        vo.setSellerOrderNo(StringUtils.trim(json.getString("sellerOrderNo")));
        vo.setIsRepeat(json.getString("repeatable"));

        // 添加增值服务构建信息
        buildOrderVasInfo(json, vo);

        return vo;

    }

    private void buildOrderVasInfo(JSONObject json, OutboundOrderVo vo) {

        if (!json.containsKey("VASList")) {
            return;
        }
        JSONArray vasArr = json.getJSONArray("VASList");
        if (vasArr == null || vasArr.isEmpty()) {
            return;
        }
        List<OutboundOrderValueAddedServiceVo> vasList = new ArrayList<OutboundOrderValueAddedServiceVo>();
        for (int i = 0; i < vasArr.size(); i++) {
            JSONObject vasServiceJson = vasArr.getJSONObject(i);
            OutboundOrderValueAddedServiceVo serviceVo = new OutboundOrderValueAddedServiceVo();
            serviceVo.setServiceCode(vasServiceJson.getString("serviceCode"));
            // 校验serviceCode重复性
            checkDuplicatedServiceCode(vasList, serviceVo.getServiceCode());
            List<OutboundOrderVasAttributeVo> vasAttributeVoList = new ArrayList<OutboundOrderVasAttributeVo>();
            JSONArray attrArray = vasServiceJson.getJSONArray("attrList");
            for (int j = 0; j < attrArray.size(); j++) {
                JSONObject attrJson = attrArray.getJSONObject(j);
                OutboundOrderVasAttributeVo attrVo = new OutboundOrderVasAttributeVo();
                attrVo.setAttributeKey(attrJson.getString("attrCode"));
                attrVo.setAttributeValue(attrJson.getString("attrValue"));
                attrVo.setServiceCode(serviceVo.getServiceCode());
                // 校验attrCode重复性
                checkDuplicatedAttrCode(vasAttributeVoList, attrVo.getAttributeKey());
                vasAttributeVoList.add(attrVo);
            }
            serviceVo.setVasAttributeVoList(vasAttributeVoList);
            vasList.add(serviceVo);
        }
        vo.setVasList(vasList);

    }

    private void checkDuplicatedServiceCode(List<OutboundOrderValueAddedServiceVo> vasList, String serviceCode) {
        if (CollectionUtils.isEmpty(vasList)) {
            return;
        }
        for (OutboundOrderValueAddedServiceVo serviceVo : vasList) {
            if (serviceVo.getServiceCode().equals(serviceCode)) {
                throw new ApiException(ErrorCode.VAS_CANNOT_BE_REPEAT, serviceCode);
            }
        }
    }

    private void checkDuplicatedAttrCode(List<OutboundOrderVasAttributeVo> attrList, String attrCode) {
        if (CollectionUtils.isEmpty(attrList)) {
            return;
        }
        for (OutboundOrderVasAttributeVo attrVo : attrList) {
            if (attrVo.getAttributeKey().equals(attrCode)) {
                throw new ApiException(ErrorCode.VAS_ATTRIBUTE_CANNOT_BE_REPEAT, attrVo.getServiceCode(), attrCode);
            }
        }
    }

    public WarehouseInfo buildWarehouseInfo(WarehouseVo warehouseVo) {
        WarehouseInfo dispatchWarehouseInfo = new WarehouseInfo();
        dispatchWarehouseInfo.setCountryCode(warehouseVo.getCountryCode());
        dispatchWarehouseInfo.setCountryName(warehouseVo.getCountry());
        dispatchWarehouseInfo.setWarehouseCode(warehouseVo.getCode());
        dispatchWarehouseInfo.setWarehouseName(warehouseVo.getName());

        return dispatchWarehouseInfo;
    }

    /**
     * 构建订单作废轨迹
     */
    private void buildVoidOrderTrack(OutboundOrderVo vo, Map<String, Object> map) {
        // 异步查询作废订单的轨迹信息
        if (EnumConstant.OrderStatus.VO.getStatus().equals(vo.getStatus())) {
            QueryOrderTrackingCommand trackingCommand = new QueryOrderTrackingCommand();
            trackingCommand.setOrderNo(vo.getOrderNo());
            trackingCommand.setStatus(EnumConstant.OrderStatus.VO.getStatus());
            try {
                OutboundOrderTrackingVo trackingVo = outboundOrderTrackingService.getOrderTrackingVo(trackingCommand);
                if (null != trackingVo) {
                    map.put("isOperateByWinit", trackingVo.getIsOperateByWinit());
                    map.put("reasonForVoid", trackingVo.getMark());
                }
            } catch (Exception e) {
                logger.error("根据订单号[{}]查询轨迹信息失败,错误：{}", vo.getOrderNo(), e);
            }
        }
    }
}
